import json
import logging
import socket
import sys
import time
from collections import Counter
from threading import Thread, Event

# from OpenSSL.rand import status
from flask import Flask, Response, request,redirect,url_for,send_file,send_from_directory
from flask_cors import CORS
# from dataStore import GlobalVar
from util import get_camera_list
from SubFunction import *
from inference_old import GenModule

logger = logging.getLogger("yolov5")
logger.setLevel(level=logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

console = logging.StreamHandler()
console.setLevel(logging.INFO)

logger.addHandler(handler)
logger.addHandler(console)

import configparser
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
cf = configparser.ConfigParser()
cf.read(os.path.join(BASE_DIR,"config.ini"), encoding='UTF-8')
front_weight=cf.get("weight","front_weight")
back_weight=cf.get("weight","back_weight")
class Appfront:
    def __init__(self,gpu_id):
        self.app=Flask(__name__)
        self.setup_routes()
        CORS(self.app)
        self.program={}
        self.send_data = None
        self.personTrack = False
        self.src_list=[]
        self.exe_camera_list=[]
        self.imagesize = 1280
        self.is_class = 0
        self.person_type=1
        self.device=gpu_id
        self.camera_list = []
        self.interval_frame=0
        self.camera_map = {}
        self.thread_wait = False
        self.started_evt = Event()
        self.hoisting=None
        self.frameNum=1
        self.stu_port=0
        self.func_dict= {
        '1': GenModule,  # 学生
        '2': GenModule,  # 教师
    }
        self.weights_dict = {
            '1': [os.path.join(BASE_DIR,front_weight)],
            '2': [os.path.join(BASE_DIR,back_weight)],
        }

    def run(self, host, port):
        print("app")
        self.stu_port=int(port)
        print(self.stu_port)
        self.app.run(host=host, port=port)
    def gen1(self,type):
        while True:
            if len(self.camera_map) != 0:
                frame = self.camera_map[type]
            else:
                frame = 2
                frame.to_bytes(4, byteorder='little', signed=True)
            # 使用generator函数输出视频流， 每次请求输出的content类型是image/jpeg
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

    def workThred(self,hoisting, person_type, started_evt):
        print('countdown starting')
        # data_store = GlobalVar()
        while True:
            if self.thread_wait:
                started_evt.wait()
                # print("主线程暂停")
                continue
            start_time = time.time()
            # 检测每一帧的检测结果[L,NL]
            send_data = hoisting.execute_func()

            # 每一帧的画面
            self.camera_map = hoisting.camera_map
            hoisting.class_is = self.is_class
            # 判断是否上下课，并发送图片
            if hoisting.class_is == 1: # 下课
                hoisting.clear_variable()
                self.is_class = 0
            if hoisting.class_is == 2:
                if person_type == '2': # 上课
                    hoisting.send_points()
                self.is_class = 0

            # Thread(target=hoisting.senf_m).start()
            # hoisting.senf_m()
            end_time = round(time.time() - start_time, 3)
            # self.frameNum = self.frameNum + 1
            # print(f"第{self.frameNum - 1}帧")
            print("帧总的推理时间：", end_time)
            # else:
            #     print("网络已中断，请检测网络连接................")


    def workthread1(self,hoisting, names):
        while True:
            hoisting.resutl_save(names)


    def workthread2(self,hoisting):
        while True:
            hoisting.save_img()
    def common_fun(self,hoisting, person_type):
        self.hoisting=hoisting
        print("开始执行")
        t = Thread(target=self.workThred, args=(hoisting, person_type, self.started_evt), daemon=True)
        t.start()
        print('countdown is running')
        data = {
            "code": 200
        }
        return json.dumps(data)
    def setup_routes(self):
        @self.app.route('/isLive',methods=['GET', 'POST'])#判断这个flask进程是否存在
        def is_live():
            data = {
                "code": 200,
                "msg": "isLive",
                "data": {}
            }
            return json.dumps(data)
        @self.app.route('/get_stream', methods=['GET', 'POST'])  # 这个地址返回视频流响应
        def test_redis():
            # gas: video:1: name
            alarm_type = request.args.get("type")
            print("视频流参数：", alarm_type)
            # camera_id=alarm_type.split("gas:video:")[1].split(":")[0]
            # # print("=========",self.hoisting.camera_list)
            # suoyi=self.hoisting.camera_list.index(int(camera_id))
            # self.hoisting.tuiliu[suoyi]=True
            return Response(self.gen1(alarm_type), mimetype='multipart/x-mixed-replace; boundary=frame')

        @self.app.route('/open_get_stream', methods=['GET', 'POST'])  # 这个地址返回视频流响应
        def open_stream():
            data = request.get_data()
            data=json.loads(data)
            camera_id=data['camera_id']
            suoyi=self.hoisting.camera_list.index(int(camera_id))
            self.hoisting.tuiliu[suoyi]=True
            return {
                "code": 200,
                "msg": "success",
                "data": {}
            }

        @self.app.route('/shutdown_get_stream', methods=['GET', 'POST'])  # 这个地址返回视频流响应
        def shutdown_stream():
            data = request.get_data()
            data=json.loads(data)
            camera_id=data['camera_id']
            suoyi=self.hoisting.camera_list.index(int(camera_id))
            self.hoisting.tuiliu[suoyi]=False
            return {
                "code": 200,
                "msg": "success",
                "data": {}
            }
        # @self.app.route('/get_person_num', methods=['GET', 'POST'])
        # def get_person_num():
        #     sumNum = GlobalVar().numCount(GlobalVar.detectionRes[-1]["detectRes"])
        #     data = {"code": 200, "msg": "success", "data": sumNum}
        #     return json.dumps(data)

        @self.app.route('/class_begin', methods=['GET'])
        def class_begin():
            self.is_class = 1
            data = {
                "code": 200,
                "msg": "success",
                "data": {}
            }
            return json.dumps(data)


        @self.app.route('/class_end', methods=['GET'])
        def class_end():
            self.is_class = 2
            data = {
                "code": 200,
                "msg": "success",
                "data": {}
            }
            return json.dumps(data)
        # @self.app.route('/<path:filename>', methods=['GET'])
        # def get_file(filename):
        #     # 指定静态文件夹为根目录
        #     root_dir = self.app.root_path
        #     print("./"+filename)
        #     # 使用 send_from_directory 函数发送文件
        #     return send_from_directory("./"+filename, filename)
        # @self.app.route('/getBehaviorNum', methods=['GET', 'POST'])
        # def getbehaviornum():
        #
        #     actions_data = GlobalVar().actionNum()
        #     viedo_frame = list(actions_data.keys())[0]
        #     actions_num = list(actions_data.values())[0]
        #     print("-------正在统计当前人数--------")
        #     data = {"code": 200, "msg": "retrieved the data", "data": actions_num}
        #     return json.dumps(data)

        @self.app.route('/stop', methods=["GET"])  # 这个地址返回视频流响应
        def stop():
            self.thread_wait = True
            print("结束执行")
            data = {
                "code": 200,
                "msg": "算法结束",
                "data": {}
            }
            return json.dumps(data)

        @self.app.route('/recover', methods=['GET'])
        def recover():
            self.started_evt.set()
            self.thread_wait=False
            data = {
                "code": 200,
                "msg": "主线程恢复",
                "data": {}
            }
            print("主线程恢复")
            return json.dumps(data)
        # 支持每秒分析图像不少于5帧
        # @self.app.route('/calculateFiveFrameTime', methods=['POST', 'GET'])
        # def calculatFiveFrameTime():
        #     frame500_detect_time = GlobalVar.Frame500_detect_time
        #     print(frame500_detect_time)
        #     if frame500_detect_time == 0:
        #         return "稍等一下，马上计算出来..."
        #     return "1秒钟检测帧数量为：" + str(round((500 / int(frame500_detect_time))))
        #
        # # 40分钟内课程内模型分析识别不少于10000帧
        # @self.app.route('/calculate_10000_FrameTime', methods=['POST', 'GET'])
        # def calculate_10000_FrameTime():
        #     time_10000_frame_detect = GlobalVar.Frame10000_detect_time
        #     if time_10000_frame_detect == 0:
        #         return "10000帧还没检测到，稍等片刻..."
        #     return "10000帧检测帧时间为：" + str(round(time_10000_frame_detect / 60)) + "分钟"


        @self.app.route('/start', methods=['POST', 'GET', 'OPTIONS'])  # 这个地址返回视频流响应
        def start():
            # if request.method == 'OPTIONS':
            #     # 处理 OPTIONS 请求
            #     response_headers = {
            #         'Access-Control-Allow-Origin': '*',
            #         'Access-Control-Allow-Methods': 'POST',
            #         'Access-Control-Allow-Headers': 'Content-Type'
            #     }
            #     return ('', 204, response_headers)

            data = request.get_data()
            # data=get_camera_list(self.stu_port)  #正式运行时打开这个，从后端获取视频流数据
            data = json.loads(data)
            print("data:::::::::::;", type(data))

            for data_in in data:
                if data_in['camera_id'] not in self.camera_list:
                    self.src_list.append(data_in['path'])
                    self.camera_list.append(data_in['camera_id'])
                    self.exe_camera_list.append(data_in['camera_id'])
                    self.person_type = data_in["person_type"]
            if len(self.exe_camera_list) > 0:
                if self.person_type == 1:
                    self.interval_frame = 0  # 跳帧检测
                Func = self.func_dict[str(self.person_type)]  # 类
                print(self.weights_dict[str(self.person_type)])
                sub_weight = self.weights_dict[str(self.person_type)]  # 权重
                sub_addr = self.src_list
                params = {
                    "camera_id": 0,
                    "location":"classroom_back" ,
                    "created_at": "",
                    "data_id": "",
                    "event_level": "",
                    "event_type": "",
                    "total_people": 0,
                    "trajectory":[],
                    "screenshot_url": "",
                    "video_url": ""
                }
                sub_func = GenModule(src_list=sub_addr,  # 视频源
                                     weight=sub_weight,  # 权重
                                     params=params,
                                     stu_port=self.stu_port,
                                     fps_show=False,  # fps显示 # 丢帧模拟
                                     track=self.personTrack,  # 跟踪
                                     msg_send=True,  # 警报发送
                                     imagesize=self.imagesize,
                                     half=False,
                                     camera_list=self.exe_camera_list,  # 摄像头数组
                                     Time_time=self.interval_frame,  # 隔多少帧检测一次
                                     device=self.device,
                                     COUNTS=5,  # 间隔30帧
                                     FramesListening=5,  # 听讲人数，间隔5秒
                                     FramesPeople=1,  # 教室人数，间隔一分钟
                                     )
                status = self.common_fun(hoisting=sub_func, person_type=self.person_type)

                return status






if __name__ == '__main__':
    gpu_id = sys.argv[1]
    host=sys.argv[2]
    port=sys.argv[3]
    # gpu_id = 0
    # host='0.0.0.0'
    # port=5000
    Appfront(gpu_id).run(host=host, port=port)

